package com.pactera.sz.cmb202101.utils;

import com.alibaba.fastjson.JSONObject;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 获取请求ip地址工具类
 *
 * @author guangming
 * @version 1.0
 * @date 2020/8/27/027 16:24
 **/
public class IpUtils {

    /**
     * 获取访问ip
     *
     * @param request 用户请求
     * @return java.lang.String
     * @author guangming
     * @date 2020/8/27/027 16:29
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
                //根据网卡取本机配置的IP
                InetAddress ipNet = null;
                try {
                    ipNet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                ipAddress = ipNet == null ? "unknown" : ipNet.getHostAddress();
            }
        }
        //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15) { //"***.***.***.***".length() = 15
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

    /**
     * 获取ip归属地
     *
     * @param request 用户请求
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author guangming
     * @date 2020/8/28/028 9:46
     */
    public static Map<String, String> getIpArea(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        StringBuilder ipArea = new StringBuilder();
        String ipAddress = getIpAddr(request);
        List<String> area;
        try {
            String str = getJsonContent("https://api.ip138.com/ipv4/?ip=" + ipAddress + "&datatype=jsonp&token=e77d1c40c7296bf9ef92377a02b5476e");
            //判断返回信息是否有效
            if (!str.isEmpty()) {
                JSONObject obj = JSONObject.parseObject(str);
                String ret = (String) obj.get("ret");
                //判断归属地是否获取成功
                if (ret.equals("ok")) {
                    area = (List<String>) obj.get("data");
                    area = area.subList(0, 4);
                    for (String s : area) {
                        if (!s.isEmpty()) {
                            ipArea.append(s);
                            ipArea.append("/");
                        }
                    }
                    ipArea.replace(ipArea.lastIndexOf("/"), ipArea.lastIndexOf("/") + 1, "");
                } else {
                    ipArea = new StringBuilder("未知归属地");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            ipArea = new StringBuilder("归属地查询异常");
        }
        map.put(ipAddress, ipArea.toString());
        return map;
    }

    /**
     * 与ip归属地查询接口建立连接查询，返回ip归属地信息
     *
     * @param urlStr 请求的url
     * @return java.lang.String
     * @author guangming
     * @date 2020/8/28/028 9:59
     */
    public static String getJsonContent(String urlStr) {
        try {// 获取HttpURLConnection连接对象
            URL url = new URL(urlStr);
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            // 设置连接属性
            httpConn.setConnectTimeout(3000);
            httpConn.setDoInput(true);
            httpConn.setRequestMethod("GET");
            // 获取相应码
            int respCode = httpConn.getResponseCode();
            if (respCode == 200) {
                return ConvertStream2Json(httpConn.getInputStream());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 将网络请求获取的归属地数据以流的形式读取，转换成字符串。
     *
     * @param inputStream 数据输入流
     * @return java.lang.String
     * @author guangming
     * @date 2020/8/28/028 11:11
     */
    private static String ConvertStream2Json(InputStream inputStream) {
        String jsonStr = "";
        // ByteArrayOutputStream相当于内存输出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        // 将输入流转移到内存输出流中
        try {
            while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) {
                out.write(buffer, 0, len);
            }
            // 将内存流转换为字符串
            jsonStr = new String(out.toByteArray());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jsonStr;
    }
}
